/*
 * sniffer.c
 *
 *  Created on: 2010-12-8
 *      Author: root
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h> /* 提供 ETH_P_ALL */
#include <net/if_arp.h>


//#define BUFSIZE 2048
#include "sniffer.h"



/********定义函数区************************/



/*********************************************/


//对MAC头进行解包
int decode_eth(const u_char *buf)
{
    struct ethhdr *eth = (struct ethhdr *) buf;

    printf("\n MAC header");
    printf("\n Destination Address: %02X:%02X:%02X:%02X:%02X:%02X",/*目的MAC地址*/
          HWADDR(eth->h_dest));
    printf("\n Source Address: %02X:%02X:%02X:%02X:%02X:%02X",/*源MAC地址*/
          HWADDR(eth->h_source));
    printf("\n Type: %02X-%02X", PWORD(eth->h_proto));/*协议种类*/

    switch (ntohs(eth->h_proto))//判断协议是？，可添加....
	{
    case ETH_P_IP:
          return decode_ip((u_char *)&eth[1]);
    case ETH_P_ARP:
          return decode_arp((u_char *)&eth[1]);
    default:
          return -1;
    	}
    return 0;
}

//arp报文解包
int decode_arp(const u_char *buf)
{
    struct ether_arp *arph = (struct ether_arp *) buf;

    printf("\n Address Resolution Protocol");
    printf("\n Hardware Type: %d", ntohs(arph->arp_hrd));
    printf("\n Protocol Type: %02X-%02X", PWORD(arph->arp_pro));
    printf("\n Length of Hardware Address: %d", arph->arp_hln);
    printf("\n Length of Protocol Address: %d", arph->arp_pln);
    printf("\n Operation Code: %d", ntohs(arph->arp_op));
    printf("\n Sender`s Hardware Address: %02X:%02X:%02X:%02X:%02X:%02X",
          HWADDR(arph->arp_sha));
    printf("\n Sender`s IP Address: %d.%d.%d.%d", NIPQUAD(arph->arp_spa));
    printf("\n Target`s Hardware Address: %02X:%02X:%02X:%02X:%02X:%02X",
          HWADDR(arph->arp_tha));
    printf("\n Target`s IP Address: %d.%d.%d.%d", NIPQUAD(arph->arp_tpa));

    return 0;
}


//ip报文解包
int decode_ip(const u_char *buf)
{
    struct iphdr *iph = (struct iphdr *) buf;
    printf("\n IPv4 header");
    printf("\n Version: %d", iph->version);
    printf("\n Header length: %d (%d bytes)", iph->ihl, iph->ihl*4);
    printf("\n Type of service (TOS):0x%02X", iph->tos);
    printf("\n Total length: %d", ntohs(iph->tot_len));
    printf("\n Identification: %d", ntohs(iph->id));
    printf("\n Flags: %02X %02X", PWORD(iph->frag_off));
    printf("\n Time to Live (TTL): %d hops", iph->ttl);
    printf("\n Protocol: %d", iph->protocol);
    printf("\n Checksum: 0x%02X%02X", PWORD(iph->check));
    printf("\n Source IP Address: %d.%d.%d.%d", NIPQUAD(iph->saddr));
    printf("\n Destination IP Address: %d.%d.%d.%d", NIPQUAD(iph->daddr));

    switch (iph->protocol) //判断ip协议类型
    {
    	case IPPROTO_TCP:
          	return decode_tcp((u_char *)&iph[1]);
    	case IPPROTO_UDP:
          	return decode_udp((u_char *)&iph[1]);
    	default:
          	return -1;
    	}
    return 0;
}

int decode_tcp(const u_char *buf)//tcp报文解包
{
    struct tcphdr *tcph = (struct tcphdr *) buf;

    printf("\n TCP header");
    printf("\n Source port: %d", ntohs(tcph->source));
    printf("\n Destination port: %d", ntohs(tcph->dest));
    printf("\n Sequence number: %u", ntohl(tcph->seq));
    printf("\n Acknowledegment number: %u", ntohl(tcph->ack_seq));
    printf("\n Header length: %d (%d bytes)", tcph->doff, tcph->doff*4);
    printf("\n Reserved: 0x%X", tcph->res1);
    printf("\n Flags: r:%d,u:%d,a:%d,p:%d,r:%d,s:%d,f:%d",
    		tcph->res2, tcph->urg, tcph->ack, tcph->psh,tcph->rst, tcph->syn, tcph->fin);
    printf("\n Window size: %d", ntohs(tcph->window));
    printf("\n Checksum: 0x%02X%02X", PWORD(tcph->check));
    printf("\n Urgent pointer: %d", ntohs(tcph->urg_ptr));

    return 0;
}

int decode_udp(const u_char *buf)//udp报文解包
{
    struct udphdr *udph = (struct udphdr *) buf;

    printf("\n UDP header");
    printf("\n Source Port: %d", ntohs(udph->source));
    printf("\n Destination Port: %d", ntohs(udph->dest));
    printf("\n Length: %d bytes", ntohs(udph->len));
    printf("\n Checksum: 0x%X", udph->check);

    return 0;
}


//格式输出数据内容
void hex_print(const u_char *buf, int len, int offset)
{
    u_int i, j, jm;
    int c;

    printf("\n");
    for (i = 0; i < len; i += 0x10)
	{
          printf(" %04x: ", (u_int)(i + offset));
          jm = len - i;
          jm = jm > 16 ? 16 : jm;

          for (j = 0; j < jm; j++)
		{
                	if ((j % 2) == 1)
                    	printf("%02x ", (u_int) buf[i+j]);
                	else printf("%02x", (u_int) buf[i+j]);
          	}
          for (; j < 16; j++)
		{
                	if ((j % 2) == 1) printf("   ");
                	else printf(" ");
          	}
          printf(" ");

	  for (j = 0; j < jm; j++)
		{
                	c = buf[i+j];
                	c = isprint(c) ? c : '.';
                	printf("%c", c);
          	}
          printf("\n");
    	}
}
